/*
 * CCVisu is a tool for visual graph clustering
 * and general force-directed graph layout.
 * This file is part of CCVisu.
 *
 * Copyright (C) 2005-2011  Dirk Beyer
 *
 * CCVisu is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * CCVisu is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with CCVisu; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please find the GNU Lesser General Public License in file
 * license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
 *
 * Dirk Beyer    (firstname.lastname@uni-passau.de)
 * University of Passau, Bavaria, Germany
 */
package org.sosy_lab.ccvisu;

import java.io.IOException;
import java.util.logging.Level;

import org.sosy_lab.ccvisu.ConfigurationCreator.InvalidCmdlineArgumentException;
import org.sosy_lab.ccvisu.graph.GraphData;
import org.sosy_lab.ccvisu.writers.Writer;
import org.sosy_lab.ccvisu.writers.WriterGui;
import org.sosy_lab.common.LogManager;
import org.sosy_lab.common.configuration.Configuration;
import org.sosy_lab.common.configuration.InvalidConfigurationException;
import org.sosy_lab.common.configuration.Option;
import org.sosy_lab.common.configuration.Options;

/**
 * Main class of the CCVisu package.
 * Contains the main program and some auxiliary methods.
 */
@Options
public class CCVisu {

  /** indicates whether CCVisu should be running with or without a gui */
  @Option(name="gui",
      description="GUI (provides a window to set options)")
  private boolean             guiMode = false;

  /**
   * Main program. Performs the following steps.
   * 1) Parses and handles the command line options.
   * 2) Processes the actual task.
   * @param args  Command line arguments.
   */
  public static void main(String[] args) {
    Configuration config = null;
    LogManager logger = null;

    // Create required instances
    try {
      try {
        config = ConfigurationCreator.create(args);
      } catch (InvalidCmdlineArgumentException e) {
        System.err.println("Could not parse command line arguments: "
            + e.getMessage());
        System.exit(1);
      } catch (IOException e) {
        System.err.println("Could not read config file " + e.getMessage());
        System.exit(1);
      }

      logger = new LogManager(config);

    } catch (InvalidConfigurationException e) {
      System.err.println("Invalid configuration: " + e.getMessage());
      System.exit(1);
    }

    // - Enhance usability when used on Mac OS.
    System.setProperty("apple.laf.useScreenMenuBar", "true");
    System.setProperty("com.apple.mrj.application.apple.menu.about.name",
        "CCVisu");

    // Run CCVisu.
    new CCVisu(config, logger);
  }

  /**
   * Creates the main object and finished the initialization of CCVisu.
   * Afterwards the application itself is started.
   */
  public CCVisu(Configuration config, LogManager logger) {
    try {
      // Finalize creation and configuration of main objects.
      config.inject(this);
      CCVisuOptions options = new CCVisuOptions(config, new GraphData(logger));
      CCVisuController controller = new CCVisuController(config, logger);

      // Run CCVisu depending on the operation mode
      if (guiMode) {
        // run with the graphical user interface (Swing)
        Writer gui = new WriterGui(controller, options, config, logger);
        gui.write();
      } else {
        // run in command line mode
        controller.process(options, config);
      }
    } catch (InvalidConfigurationException e) {
      logger.logUserException(Level.SEVERE, e, "Invalid configuration.");
      System.exit(1);
    } catch (Exception e) {
      logger.logException(Level.SEVERE, e, "");
      System.exit(1);
    }
  }
}
